#ifndef ESP_UDP_COMM_H
#define ESP_UDP_COMM_H

#include <WiFi.h>
#include <WiFiUdp.h>
#include <functional>
#include <map>

#define UDP_BUFFER_SIZE 256
#define DEFAULT_UDP_PORT 4210

class ESP_UDP_Comm
{
public:
    // 回调函数类型：接收字符串内容
    typedef std::function<void(const String &payload)> Callback;

    // 构造函数
    ESP_UDP_Comm();

    // 初始化WiFi（可选使用静态IP）
    void begin(const char *ssid, const char *password, uint16_t port = DEFAULT_UDP_PORT);

    // 使用静态IP初始化
    void beginWithStaticIP(const char *ssid, const char *password, IPAddress localIP, IPAddress gateway, IPAddress subnet, IPAddress dns = IPAddress(8, 8, 8, 8), uint16_t port = DEFAULT_UDP_PORT);

    // 每次循环中调用，用于处理接收到的数据
    void loop();

    // 注册通道回调函数
    void registerCallback(int channel, Callback cb);

    // 广播发送（发送给同一局域网内所有设备）
    void sendAll(const char *fmt, ...);
    // 向指定IP地址发送格式化UDP消息
    void sendToIP(IPAddress ip, const char *fmt, ...);
    // 向指定 IP（字符串形式）发送格式化UDP数据
    void sendTo(const char *ipStr, const char *fmt, ...);

private:
    WiFiUDP udp;
    uint16_t localPort;
    char udpBuffer[UDP_BUFFER_SIZE];
    std::map<int, Callback> callbacks;

    // 内部函数：处理接收到的UDP数据包
    void processPacket(const char *data);
};

#endif
/*
实例用法:
绑定静态ip：
 // 使用静态IP方式初始化（推荐用于UDP设备）
    IPAddress localIP(192, 168, 1, 101);
    IPAddress gateway(192, 168, 1, 1);
    IPAddress subnet(255, 255, 255, 0);

    comm.beginWithStaticIP("你的WiFi", "你的密码", localIP, gateway, subnet);
发送端初始化:
#include "ESP_UDP_Comm.h"

ESP_UDP_Comm comm;

void setup() {
    Serial.begin(115200);
    comm.begin("你的WiFi", "你的密码");
}
发送:comm.sendAll("@$c:%d,%d,%d#\n", 1, 23, 45);  // 灵活格式化发送
    comm.sendAll("@$s:{\"x\":%d,\"y\":%d}#\n", 100, 200);  // 发送JSON风格数据
    // 示例：向指定IP地址发送
    IPAddress targetIP(192, 168, 1, 123);  // 替换成你目标设备的IP
    comm.sendTo(targetIP, "@$c:1,99,88#\n");
    或者函数重载
    comm.sendTo("192.168.1.4", "@$c:2,99#\n");
接收端初始化以及注册回调函数:
ESP_UDP_Comm comm;

// 自定义回调函数，接收原始 payload 字符串
void handler_ch3(const String& payload) {
    Serial.println("通道3收到数据：" + payload);

    // 示例：你可以自行用 sscanf 或 split 来解析
    int a, b;
    if (sscanf(payload.c_str(), "%d,%d", &a, &b) == 2) {
        Serial.printf("解析为两个整数：%d 和 %d\n", a, b);
    }
}

void setup() {
    Serial.begin(115200);
    comm.begin("你的WiFi名", "你的WiFi密码");  // 请替换成你的WiFi信息

    comm.registerCallback(3, handler_ch3); // 注册通道3的回调处理
}

comm.loop(); // 必须轮询接收

*/